package com.zhijian.warehouse.manage.service.impl;

import cn.hutool.core.util.RandomUtil;
import com.zhijian.autoconfigure.cache.CacheClient;
import com.zhijian.util.AssertUtil;
import com.zhijian.util.BeanUtil;
import com.zhijian.util.EncryptUtil;
import com.zhijian.util.JsonUtil;
import com.zhijian.util.token.TokenBean;
import com.zhijian.util.token.TokenUtil;
import com.zhijian.warehouse.manage.config.Constants;
import com.zhijian.warehouse.manage.entity.dto.UserDto;
import com.zhijian.warehouse.manage.entity.po.User;
import com.zhijian.warehouse.manage.entity.vo.request.LoginVo;
import com.zhijian.warehouse.manage.entity.vo.response.AuthVo;
import com.zhijian.warehouse.manage.enums.ResponseEnum;
import com.zhijian.warehouse.manage.enums.StatusEnum;
import com.zhijian.warehouse.manage.enums.SystemEnum;
import com.zhijian.warehouse.manage.service.LoginAbstract;
import com.zhijian.warehouse.manage.service.TokenService;
import com.zhijian.warehouse.manage.service.UserService;
import com.zhijian.warehouse.manage.util.AssertCommonUtil;
import com.zhijian.warehouse.manage.util.QRCodeGenerator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.security.SecureRandom;
import java.util.concurrent.TimeUnit;

/**
 * @author HCG
 * @version 1.0
 * @date 2022/1/17
 */
@Service
@Slf4j
public class H5LoginServiceImpl extends LoginAbstract {

    @Autowired
    private UserService userService;

    @Autowired
    private CacheClient cacheClient;

    @Autowired
    private TokenService tokenService;

    @Override
    public AuthVo login(LoginVo vo) {
        //改成学号
        User user = userService.selectByJobNumber(vo.getJobNumber());
        AssertCommonUtil.check(BeanUtil.isEmpty(user), "用户不存在");
        //给前台传过来的密码加盐，然后加密
        String password = EncryptUtil.password(vo.getPassword(), user.getSalt());
        AssertCommonUtil.check(!password.equals(user.getPassword()), ResponseEnum.LOGIN_WRONG.cn);
        AssertCommonUtil.check(user.getStatus() != StatusEnum.NORMAL.getCode().byteValue(), "禁止登录");
        UserDto userDto = UserDto.mergeFromPo(user);
        assert userDto != null;
        userDto.setSort(RandomUtil.randomInt(99999));
        userDto.setType(1);
        //生成新的token(账号、密码、生成密钥、过期时间、登陆时间)
        TokenBean tokenBean = new TokenBean(Constants.TOKEN_ACCESS_KEY, Constants.TOKEN_SECRET_KEY,
                "1.0", "login", "POST", null, JsonUtil.toString(userDto));
        String token = TokenUtil.generateToken(tokenBean, 0);
        cacheClient.setExSeconds(String.format(SystemEnum.H5.getLoginTokenKey(), user.getPhone(), userDto.getSort()), token, SystemEnum.H5.getLoginExpireTime());
        //缓存生成token的用户信息
        cacheClient.setExSeconds(String.format(SystemEnum.H5.getUserKey(), token), JsonUtil.toString(userDto), SystemEnum.H5.getLoginExpireTime());
        return AuthVo.builder()
                .token(token)
                .user(AuthVo.UserDetailVo.builder()
                        .id(user.getId())
                        .name(user.getName())
                        .phone(user.getPhone())
                        .userName(user.getUserName())
                        .build())
                .build();
    }

    @Override
    public boolean logout(String token) {
        UserDto userDto = tokenService.getUserDtoByToken(SystemEnum.H5, token);
        if (userDto == null) {
            return false;
        }
        //清空token缓存
        cacheClient.del(String.format(SystemEnum.H5.getLoginTokenKey(), userDto.getPhone(), userDto.getSort()));
        //清空token对应用户信息
        cacheClient.del(String.format(SystemEnum.H5.getUserKey(), token));
        return true;
    }

    public String createQrcode(String token) {
        //生成二维码
        try {
            String format = cacheClient.get(String.format(Constants.Redis.QRCODE_KEY, token));
            if (BeanUtil.isNotEmpty(format))
                cacheClient.del(format);
            cacheClient.del(String.format(Constants.Redis.QRCODE_KEY, token));
            SecureRandom secureRandom = new SecureRandom();
            StringBuilder randomTokenBuilder = new StringBuilder(10);
            String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            for (int i = 0; i < 10; i++) {
                int index = secureRandom.nextInt(characters.length());
                randomTokenBuilder.append(characters.charAt(index));
            }
            String randomToken = randomTokenBuilder.toString();
            format = String.format("%s", randomToken);
            cacheClient.set(String.format(Constants.Redis.QRCODE_KEY, token), format, 5 * 60, TimeUnit.SECONDS);
            cacheClient.set(format, token, 5 * 60, TimeUnit.SECONDS);
            return QRCodeGenerator.generateQRCode(format);
        } catch (Exception e) {
            log.error(String.format("create qrcode error:%s,token:%s", e.getMessage(), token));
            AssertUtil.check(true, "登录码获取失败，请联系管理员");
        }
        return null;
    }
}
